package org.jmhome.blog.controller;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpSession;

import org.jmhome.blog.exception.UserNotAutorityException;
import org.jmhome.blog.model.AttachmentFile;
import org.jmhome.blog.model.Board;
import org.jmhome.blog.model.BoardRecommandUser;
import org.jmhome.blog.model.BoardReply;
import org.jmhome.blog.model.Category;
import org.jmhome.blog.model.User;
import org.jmhome.blog.service.BoardService;
import org.jmhome.blog.service.CategoryService;
import org.jmhome.blog.service.FileService;
import org.jmhome.blog.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class BoardController {

	@Autowired
	private CategoryService categoryService;

	@Autowired
	private BoardService boardService;

	@Autowired
	private FileService fileService;

	@Autowired
	private UserService userService;

	@ModelAttribute("allCategories")
	public List<Category> getAllCategories() {
		List<Category> allCategories = categoryService.getAllCategories();
		return allCategories;
	}

	@RequestMapping(value = "/writeAndUpdateForm.do", method = RequestMethod.GET)
	public ModelAndView boardWriteAndUpdateForm(
			ModelAndView mav,
			@RequestParam(value = "boardSeq", required = false) Integer boardSeq,
			@RequestParam(value = "categoryCode") String categoryCode) {
		Board board = boardService.getBoard(boardSeq);
		mav.addObject("board", board);
		mav.addObject("categoryCode", categoryCode);
		mav.setViewName("board-write-and-update");
		return mav;
	}

	@RequestMapping(value = "/writeAndUpdateSubmit.do", method = RequestMethod.POST)
	public ModelAndView boardWriteAndUpdateSubmit(
			ModelAndView mav,
			@ModelAttribute("Board") Board board,
			@RequestParam(value = "categoryCode", defaultValue = "universe") String categoryCode,
			@RequestParam("file") MultipartFile file, HttpSession session)
			throws UserNotAutorityException, IllegalStateException, IOException {
		User user = (User) session.getAttribute("blogUser");
		if (blockBoardUpdate(board, user)) {
			throw new UserNotAutorityException();
		}

		board.setRegDate(new Date());
		Category category = categoryService.getCategory(categoryCode);
		board.setCategory(category);

		if (board.getBoardSeq() == null) {

			if (file != null) {
				List<AttachmentFile> files = insertFileToBoard(session, file,
						board);
				board.setAttachmentFile(files);
			}
			boardService.insertBoard(board);
			mav.setViewName("redirect:/category.do?categoryCode="
					+ categoryCode);
		} else {
			if (file != null) {
				List<AttachmentFile> files = insertFileToBoard(session, file,
						board);
				board.setAttachmentFile(files);
			}

			boardService.updateBoard(board);
			mav.setViewName("redirect:/boardContent.do?boardSeq="
					+ board.getBoardSeq() + "&categoryCode=" + categoryCode);
		}

		return mav;
	}

	protected List<AttachmentFile> insertFileToBoard(HttpSession session,
			MultipartFile file, Board board) throws IllegalStateException,
			IOException {
		// String filePath = WebUtils.getRealPath(session.getServletContext(),
		// "/upload");
		String filePath = System.getProperty("user.home") + File.separator
				+ "upload";
		List<AttachmentFile> files = board.getAttachmentFile();
		if (files == null) {
			files = new ArrayList<AttachmentFile>();
		}
		// System.out.println(System.getProperty("user.home"));

		String fileName = file.getOriginalFilename();
		String fileCode = "F" + System.currentTimeMillis();
		files.add(new AttachmentFile(fileCode, fileName, filePath, file
				.getSize(), board));
		// 파일 전송
		file.transferTo(new File(filePath + File.separator + fileCode));
		return files;
	}

	/**
	 * @param board
	 * @param sessionUser
	 * @return
	 */
	protected boolean blockBoardUpdate(Board board, User sessionUser) {
		Board previousBoard = boardService.getBoard(board.getBoardSeq());
		User boardUser = previousBoard.getUser();
		if (boardUser != null && sessionUser != null) {
			String boardUserEmail = boardUser.getEmail();
			String sessionUserEmail = sessionUser.getEmail();
			if (!boardUserEmail.equals(sessionUserEmail)) {
				// TODO
				return true;
			}
		} else if (boardUser == null && sessionUser != null) {
			board.setUser(sessionUser);
		}
		return false;
	}

	@RequestMapping(value = "/boardDelete.do", method = RequestMethod.GET)
	public ModelAndView boardDelete(ModelAndView mav,
			@RequestParam("boardSeq") Integer boardSeq,
			@RequestParam("categoryCode") String categoryCode) {

		boardService.deleteBoard(boardSeq);
		mav.setViewName("redirect:/category.do?categoryCode=" + categoryCode);
		return mav;
	}

	@RequestMapping(value = "/boardContent.do", method = RequestMethod.GET)
	public ModelAndView getBoardContent(ModelAndView mav,
			@RequestParam(value = "boardSeq") Integer boardSeq,
			@RequestParam(value = "categoryCode") String categoryCode,
			HttpSession session) {
		Board board = boardService.getBoard(boardSeq);

		updateBoardCount(session, board);

		List<BoardReply> replies = board.getBoardReply();
		List<BoardRecommandUser> recommandUsers = board.getRecommandUser();
		int count = replies.size();
		int recommandCount = recommandUsers.size();
		mav.addObject("board", board);
		mav.addObject("replies", replies);
		mav.addObject("count", count);
		mav.addObject("recommandCount", recommandCount);
		mav.addObject("categoryCode", categoryCode);
		mav.setViewName("board-content");
		return mav;
	}

	private void updateBoardCount(HttpSession session, Board board) {
		User user = (User) session.getAttribute("blogUser");
		String boardAttribute = user.getEmail() + board.getBoardSeq();
		Boolean beforeInquery = (Boolean) session.getAttribute(boardAttribute);
		if (beforeInquery == null) {
			session.setAttribute(boardAttribute, true);
			board.setCount(board.getCount() + 1);
			boardService.updateBoard(board);
		}
	}

	/**
	 * @param session
	 * @param boardSeq
	 * @return
	 */
	@RequestMapping("/boardRecommandCount.do")
	public @ResponseBody
	Integer boardRecommandCount(HttpSession session,
			@RequestParam(value = "boardSeq") Integer boardSeq) {
		User user = (User) session.getAttribute("blogUser");
		String userEmail = user.getEmail();
		BoardRecommandUser recommandUser = boardService.getBoardRecommandUser(
				userEmail, boardSeq);
		
		int recommandCount = 0;
		if (recommandUser == null) {
			Board board = boardService.getBoard(boardSeq);
			if (board != null) {
				recommandUser = new BoardRecommandUser();
				recommandUser.setRecommandUserEmail(userEmail);
				recommandUser.setRecommandBoard(board);
				List<BoardRecommandUser> recommandUsers = board.getRecommandUser();
				if(recommandUsers != null && !recommandUsers.isEmpty()) {
					recommandUsers.add(recommandUser);
				} else {
					recommandUsers = new ArrayList<BoardRecommandUser>();
					recommandUsers.add(recommandUser);
				}
				board.setRecommandUser(recommandUsers);
				recommandCount = board.getRecommandUser().size();
				boardService.updateBoard(board);
			}
		}
		return recommandCount;
	}

	@RequestMapping(value = "/replyWriteAndUpdateSubmit.do", method = RequestMethod.POST)
	public ModelAndView boardReplyWriteAndUpdateSubmit(
			ModelAndView mav,
			@ModelAttribute("BoardReply") BoardReply reply,
			@RequestParam(value = "boardSeq", required = false) Integer boardSeq,
			@RequestParam(value = "categoryCode") String categoryCode) {
		reply.setRegDate(new Date());
		Board board = boardService.getBoard(boardSeq);
		reply.setBoard(board);
		if (reply.getBoardReplySeq() == null) {
			boardService.insertBoardReply(reply);
		} else {
			boardService.updateBoardReply(reply);
		}
		mav.setViewName("redirect:/boardContent.do?boardSeq=" + boardSeq
				+ "&categoryCode=" + categoryCode);
		return mav;
	}

	@RequestMapping(value = "/boardReplyDelete.do", method = RequestMethod.GET)
	public ModelAndView boardReplyDelete(ModelAndView mav,
			@RequestParam("boardReplySeq") Integer boardReplySeq,
			@RequestParam("boardSeq") Integer boardSeq,
			@RequestParam(value = "categoryCode") String categoryCode) {
		boardService.deleteBoardReply(boardReplySeq);
		mav.setViewName("redirect:/boardContent.do?boardSeq=" + boardSeq
				+ "&categoryCode=" + categoryCode);
		return mav;
	}

	@RequestMapping("/fileDownload.do")
	public ModelAndView download(ModelAndView mav,
			@RequestParam("boardSeq") Integer boardSeq,
			@RequestParam("fileSeq") Integer fileSeq) {
		AttachmentFile AttachmentFile = fileService.getFile(fileSeq);
		return new ModelAndView("fileDownloadView", "attachmentFile",
				AttachmentFile);
	}

}
